package control;
import java.util.*;

import model.*;
import db.*;

/*This is the Person controller.
 * Its purpose is to give instructions towards manipulating the data concerning people, including adding, updating, deleting
 * or simply returning a person for inspection. It also has the added function of manipulating debtors, employees and contacts
 * since these all inherit properties from their superclass Person.
 */

public class PersonCtrl 
{
	private DBEmployee dbEmployee = new DBEmployee();
	private DBClient dbClient = new DBClient();
	private DBPerson dbPerson = new DBPerson();
	private DBContact dbContact = new DBContact();
	private DBDebtor dbDebtor = new DBDebtor();
	private DBCaseXEmployee dbCaseEmp = new DBCaseXEmployee();
	private DBCase dbCase = new DBCase();
	
	public PersonCtrl()
	{
		
	}
	
	// The following methods return all employees, debtors and contacts respectively in the form of an ArrayList
	//of the corresponding type.
	
	
	public ArrayList<Debtor> listAllDebtors()
	{
		ArrayList<Debtor> allDebtors = dbDebtor.getAllDebtors(false);
		return allDebtors;		
	}

	public ArrayList<Contact> listAllContacts()
	{
		ArrayList<Contact> allContacts = dbContact.getAllContacts(false);
		return allContacts;		
	}
	
	// This method creates an object of type Person (which acts as a superclass for employees, contacts and debtors) and calls
	// the methods for insertion into a database.
	
	public void createPerson(String name, String address, String zipCode, String city, String phone, String gsm, String email, String cpr) throws Exception
	{
		Person toInsert = new Person();
		toInsert.setName(name);
		toInsert.setAddress(address);
		toInsert.setZipCode(zipCode);
		toInsert.setCity(city);
		toInsert.setPhone(phone);
		toInsert.setGsm(gsm);
		toInsert.setEmail(email);
		toInsert.setCpr(cpr);
		dbPerson.insertPerson(toInsert);
	}
	
	// This method removes a person entity the database. It also makes sure that no employees, debtors or contacts 
	// with the same CPR remain, since they shouldn't exist without the corresponding Person object.
	
	public void deletePerson(String cpr)
	{
		dbPerson.deletePerson(cpr);
		deleteEmployee(cpr);
		deleteDebtor(cpr);
		deleteContact(cpr);
	}
	
	//The following 3 methods insert an employee, debtor and contact respectively in the database.
	
	public void createEmployee(String cpr, String password, String accessType, String status) throws Exception
	{
		Employee toInsert = new Employee();
		toInsert.setCpr(cpr);
		toInsert.setPassword(password);
		toInsert.setAccessType(accessType);
		toInsert.setStatus(status);
		dbEmployee.insertEmployee(toInsert);
	}
	
	public void createDebtor(String cpr, String contactCpr) throws Exception
	{
		Debtor toInsert = new Debtor();
		toInsert.setCpr(cpr);
		toInsert.setContact(dbContact.getContactCpr(contactCpr,true));
		dbDebtor.insertDebtor(toInsert);
	}
	
	public void createContact(String cpr) throws Exception
	{
		Contact toInsert = new Contact();
		toInsert.setCpr(cpr);
		dbContact.insertContact(toInsert);
	}
	
	// The 4 methods below insert an entity of the superclass Person, and also the employee, debtor and contact entities
	// to further define what that person represents in the database.
	
	public int updatePerson(String name, String address, String zipCode, String city, String phone, String gsm, String email, String cpr)
	{
		Person toUpdate = dbPerson.getPersonByCpr(cpr, false);
		toUpdate.setName(name);
		toUpdate.setAddress(address);
		toUpdate.setZipCode(zipCode);
		toUpdate.setCity(city);
		toUpdate.setPhone(phone);
		toUpdate.setGsm(gsm);
		toUpdate.setEmail(email);
		return dbPerson.updatePerson(toUpdate);
	}
	
	public void updateEmployee(String cpr, String password, String accessType, String status/*, String name, String address, String zipCode, String city, String phone, String gsm, String email*/)
	{
		Employee toUpdate = new Employee();
		toUpdate.setCpr(cpr);
		toUpdate.setPassword(password);
		toUpdate.setAccessType(accessType);
		toUpdate.setStatus(status);
		dbEmployee.updateEmployee(toUpdate);
	}
	
	public void updateDebtor(String cpr, String name, String address, String zipCode, String city, String phone, String gsm, String email, String contactCpr)
	{
		Debtor toUpdate = new Debtor();
		toUpdate.setCpr(cpr);
		toUpdate.setName(name);
		toUpdate.setAddress(address);
		toUpdate.setZipCode(zipCode);
		toUpdate.setCity(city);
		toUpdate.setPhone(phone);
		toUpdate.setGsm(gsm);
		toUpdate.setEmail(email);
		toUpdate.setContact(dbContact.getContactCpr(contactCpr, false)); 
		updatePerson(name, address, zipCode, city, phone, gsm, email, cpr);
		dbDebtor.updateDebtor(toUpdate);
	}

	public int updateContact(String cpr, String name, String address, String zipCode, String city, String phone, String gsm, String email)
	{
		Contact toUpdate = dbContact.getContactCpr(cpr,false);
		toUpdate.setName(name);
		toUpdate.setAddress(address);
		toUpdate.setZipCode(zipCode);
		toUpdate.setCity(city);
		toUpdate.setPhone(phone);
		toUpdate.setGsm(gsm);
		toUpdate.setEmail(email);
		updatePerson(cpr,name,address,zipCode,city,phone,gsm,email);
		return dbContact.updateContact(toUpdate); 
	}
	
	// These 3 methods remove an employee, contact and debtor respectively from the database. 
	
	public boolean deleteEmployee(String cpr)
	{
		return dbEmployee.deleteEmployee(cpr);
	}
	
	public boolean deleteContact(String cpr)
	{
		return dbContact.deleteContact(cpr);
	}
	
	public boolean deleteDebtor(String cpr)
	{
		return dbDebtor.deleteDebtor(cpr);
	}
		
	// These 4 methods call for a search method by CPR and return either a person, a debtor, a contact or an employee,
	// depending on which of them is used.
	
	public Person getPersonByCpr(String cpr)
	{
		return dbPerson.getPersonByCpr(cpr, false);
	}
		
	public Debtor getDebtorByCpr(String cpr)
	{
		return dbDebtor.getDebtorCpr(cpr, false);
	}
	
	public Employee getEmployeeByCpr(String cpr)
	{
		return dbEmployee.getEmployeeCpr(cpr, false);
	}
	
	public Contact getContactByCpr(String cpr)
	{
		return dbContact.getContactCpr(cpr,true);
	}
	
	public ArrayList<Employee> getAllEmployeesByStatus(String _status)
	{
		return dbEmployee.getAllEmployeesByStatus(_status, false);
	}
		
	// This method assigns an employee to a case.
	
	public void assignCase(String cpr, String id)
	{
		Employee employee = dbEmployee.getEmployeeCpr(cpr, false);
		Case thecase = dbCase.getCaseById(id, false);
		employee.addCase(thecase);
		thecase.addEmployee(employee);
		try 
		{
			dbCaseEmp.insertCaseXEmployee(employee,thecase);
		} 
		catch (Exception e) 
		{
			// TODO Auto-generated catch block and or throws exception
			e.printStackTrace();
		}
	}
	
	public void unassignCase(String cpr, String id)
	{
		Employee employee = dbEmployee.getEmployeeCpr(cpr, false);
		Case thecase = dbCase.getCaseById(id, false);
		try 
		{
			dbCaseEmp.deleteCaseXEmployee(employee, thecase);
		} 
		catch (Exception e) 
		{
			// TODO Auto-generated catch block and or throws exception
			e.printStackTrace();
		}
	}
	
	public boolean ifAssignedToCase(String cpr, String id)
	{
		return dbCaseEmp.ifAssigned(cpr, id, false);
	}
	
	// This method removes the association between an employee and a case.
	
	public void removeCase(String cpr, String id)
	{
		Employee employee = dbEmployee.getEmployeeCpr(cpr, true);
		Case thecase = dbCase.getCaseById(id,true);
		employee.removeCase(thecase);
		thecase.removeEmployee(employee);
		dbCaseEmp.deleteCaseXEmployee(employee,thecase);
	}
	
	// This method recreates the association between an employee and a case, either replacing a case with another one
	// for an employee or vice-versa.
	
	public int reassignCase(String oldcpr, String oldid, String newcpr, String newid)
	{
		Employee oldemployee = dbEmployee.getEmployeeCpr(oldcpr, true);
		Employee newemployee = dbEmployee.getEmployeeCpr(newcpr, true);
		Case oldcase = dbCase.getCaseById(oldid, true);
		Case newcase = dbCase.getCaseById(newid, true);
		oldemployee.removeCase(oldcase);
		oldcase.removeEmployee(oldemployee);
		oldemployee.addCase(newcase);
		oldcase.addEmployee(newemployee);
		return dbCaseEmp.updateCaseXEmployee(oldemployee, oldcase, newemployee, newcase);
	}
}
